//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package org_report_api_serv

import (
	"context"
	"time"

	"atomgit.com/openlinksaas-org/api-server/dao"
	"atomgit.com/openlinksaas-org/api-server/dao/org_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/user_dao"
	"atomgit.com/openlinksaas-org/api-server/utils"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/org_report_api"
	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *OrgReportApiImpl) AddDayReport(ctx context.Context, req *org_report_api.AddDayReportRequest) (*org_report_api.AddDayReportResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_report_api.AddDayReportResponse{
			Code:   org_report_api.AddDayReportResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	exist, err := org_dao.OrgInfoDao.Exist(ctx, req.OrgId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_report_api.AddDayReportResponse{
			Code:   org_report_api.AddDayReportResponse_CODE_NO_ORG,
			ErrMsg: "组织不存在",
		}, nil
	}
	exist, err = org_dao.MemberDao.Exist(ctx, req.OrgId, sessionItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_report_api.AddDayReportResponse{
			Code:   org_report_api.AddDayReportResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	reportId := uuid.NewString()
	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = org_dao.DayReportDao.Insert(sessCtx, &org_dao.DayReportInfoDbItem{
			ReportId: reportId,
			OrgId:    req.OrgId,
			BasicInfo: org_dao.BasicDayReportInfoDbItem{
				DayTime: req.BasicInfo.DayTime,
				Content: req.BasicInfo.Content,
			},
			MemberUserId: sessionItem.UserId,
			CreateTime:   nowTime,
			UpdateTime:   nowTime,
		})
		if err != nil {
			return nil, err
		}
		return &org_report_api.AddDayReportResponse{
			Code:     org_report_api.AddDayReportResponse_CODE_OK,
			ReportId: reportId,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*org_report_api.AddDayReportResponse), nil
}

func (apiImpl *OrgReportApiImpl) UpdateDayReport(ctx context.Context, req *org_report_api.UpdateDayReportRequest) (*org_report_api.UpdateDayReportResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_report_api.UpdateDayReportResponse{
			Code:   org_report_api.UpdateDayReportResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	exist, err := org_dao.OrgInfoDao.Exist(ctx, req.OrgId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_report_api.UpdateDayReportResponse{
			Code:   org_report_api.UpdateDayReportResponse_CODE_NO_ORG,
			ErrMsg: "组织不存在",
		}, nil
	}
	exist, err = org_dao.MemberDao.Exist(ctx, req.OrgId, sessionItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_report_api.UpdateDayReportResponse{
			Code:   org_report_api.UpdateDayReportResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	reportItem, err := org_dao.DayReportDao.Get(ctx, req.OrgId, sessionItem.UserId, req.ReportId)
	if err != nil {
		return &org_report_api.UpdateDayReportResponse{
			Code:   org_report_api.UpdateDayReportResponse_CODE_NO_REPORT,
			ErrMsg: "日报不存在",
		}, nil
	}

	nowTime := time.Now().UnixNano() / 1e6
	userPerm := apiImpl.calcDayReportPerm(sessionItem.UserId, reportItem, nowTime)
	if !userPerm.CanUpdate {
		return &org_report_api.UpdateDayReportResponse{
			Code:   org_report_api.UpdateDayReportResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = org_dao.DayReportDao.Update(sessCtx, req.OrgId, sessionItem.UserId, req.ReportId, &org_dao.BasicDayReportInfoDbItem{
			DayTime: req.BasicInfo.DayTime,
			Content: req.BasicInfo.Content,
		}, nowTime)
		if err != nil {
			return nil, err
		}
		return &org_report_api.UpdateDayReportResponse{
			Code: org_report_api.UpdateDayReportResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*org_report_api.UpdateDayReportResponse), nil
}

func (apiImpl *OrgReportApiImpl) ListDayReport(ctx context.Context, req *org_report_api.ListDayReportRequest) (*org_report_api.ListDayReportResponse, error) {
	emptyList := []*org_report_api.DayReportInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_report_api.ListDayReportResponse{
			Code:       org_report_api.ListDayReportResponse_CODE_WRONG_SESSION,
			ErrMsg:     "会话不存在",
			ReportList: emptyList,
		}, nil
	}
	orgItem, err := org_dao.OrgInfoDao.Get(ctx, req.OrgId)
	if err != nil {
		return &org_report_api.ListDayReportResponse{
			Code:       org_report_api.ListDayReportResponse_CODE_NO_ORG,
			ErrMsg:     "组织不存在",
			ReportList: emptyList,
		}, nil
	}
	curMemberItem, err := org_dao.MemberDao.Get(ctx, req.OrgId, sessionItem.UserId)
	if err != nil {
		return &org_report_api.ListDayReportResponse{
			Code:       org_report_api.ListDayReportResponse_CODE_NO_PERMISSION,
			ErrMsg:     "没有权限",
			ReportList: emptyList,
		}, nil
	}
	targetMemberItem, err := org_dao.MemberDao.Get(ctx, req.OrgId, req.MemberUserId)
	if err != nil {
		return &org_report_api.ListDayReportResponse{
			Code:       org_report_api.ListDayReportResponse_CODE_NO_PERMISSION,
			ErrMsg:     "没有权限",
			ReportList: emptyList,
		}, nil
	}
	//检查部门层级关系
	if !(orgItem.OwnerUserId == sessionItem.UserId || req.MemberUserId == sessionItem.UserId || curMemberItem.ParentDepartMentId == "") {
		include, err := utils.CheckIncludeDepartMent(ctx, req.OrgId, targetMemberItem.ParentDepartMentId, curMemberItem.ParentDepartMentId)
		if err != nil {
			return nil, err
		}
		if !include {
			return &org_report_api.ListDayReportResponse{
				Code:       org_report_api.ListDayReportResponse_CODE_NO_PERMISSION,
				ErrMsg:     "没有权限",
				ReportList: emptyList,
			}, nil
		}
	}

	count, err := org_dao.DayReportDao.Count(ctx, req.OrgId, req.MemberUserId, req.ListParam)
	if err != nil {
		return nil, err
	}
	reportItemList, err := org_dao.DayReportDao.List(ctx, req.OrgId, req.MemberUserId, req.ListParam, int64(req.Offset), int64(req.Limit))
	if err != nil {
		return nil, err
	}
	//获取用户信息
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, []string{req.MemberUserId})
	if err != nil {
		return nil, err
	}

	//生成结果
	nowTime := time.Now().UnixNano() / 1e6
	reportList := []*org_report_api.DayReportInfo{}
	for _, reportItem := range reportItemList {
		report := reportItem.ToDayReportInfo()
		if len(userItemList) == 1 {
			report.MemberDisplayName = userItemList[0].BasicInfo.DisplayName
			report.MemberLogoUri = userItemList[0].BasicInfo.LogoUri
		}
		report.UserPerm = apiImpl.calcDayReportPerm(sessionItem.UserId, reportItem, nowTime)
		reportList = append(reportList, report)
	}

	return &org_report_api.ListDayReportResponse{
		Code:       org_report_api.ListDayReportResponse_CODE_OK,
		TotalCount: count,
		ReportList: reportList,
	}, nil
}

func (apiImpl *OrgReportApiImpl) calcDayReportPerm(userId string, reportItem *org_dao.DayReportInfoDbItem, nowTime int64) *org_report_api.UserPerm {
	if userId != reportItem.MemberUserId {
		return &org_report_api.UserPerm{
			CanUpdate: false,
			CanRemove: false,
		}
	}
	if (nowTime - reportItem.CreateTime) > (3 * 24 * 3600 * 1000) {
		return &org_report_api.UserPerm{
			CanUpdate: false,
			CanRemove: false,
		}
	}
	return &org_report_api.UserPerm{
		CanUpdate: true,
		CanRemove: true,
	}
}

func (apiImpl *OrgReportApiImpl) GetDayReport(ctx context.Context, req *org_report_api.GetDayReportRequest) (*org_report_api.GetDayReportResponse, error) {
	emptyInfo := &org_report_api.DayReportInfo{
		BasicInfo: &org_report_api.BasicDayReportInfo{},
		UserPerm:  &org_report_api.UserPerm{},
	}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_report_api.GetDayReportResponse{
			Code:   org_report_api.GetDayReportResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
			Report: emptyInfo,
		}, nil
	}
	exist, err := org_dao.OrgInfoDao.Exist(ctx, req.OrgId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_report_api.GetDayReportResponse{
			Code:   org_report_api.GetDayReportResponse_CODE_NO_ORG,
			ErrMsg: "组织不存在",
			Report: emptyInfo,
		}, nil
	}
	exist, err = org_dao.MemberDao.Exist(ctx, req.OrgId, sessionItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_report_api.GetDayReportResponse{
			Code:   org_report_api.GetDayReportResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
			Report: emptyInfo,
		}, nil
	}

	reportItem, err := org_dao.DayReportDao.Get(ctx, req.OrgId, sessionItem.UserId, req.ReportId)
	if err != nil {
		return &org_report_api.GetDayReportResponse{
			Code:   org_report_api.GetDayReportResponse_CODE_NO_REPORT,
			ErrMsg: "日报不存在",
			Report: emptyInfo,
		}, nil
	}

	nowTime := time.Now().UnixNano() / 1e6

	report := reportItem.ToDayReportInfo()
	report.MemberDisplayName = sessionItem.DisplayName
	report.MemberLogoUri = sessionItem.LogoUri
	report.UserPerm = apiImpl.calcDayReportPerm(sessionItem.UserId, reportItem, nowTime)

	return &org_report_api.GetDayReportResponse{
		Code:   org_report_api.GetDayReportResponse_CODE_OK,
		Report: report,
	}, nil
}

func (apiImpl *OrgReportApiImpl) RemoveDayReport(ctx context.Context, req *org_report_api.RemoveDayReportRequest) (*org_report_api.RemoveDayReportResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_report_api.RemoveDayReportResponse{
			Code:   org_report_api.RemoveDayReportResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	exist, err := org_dao.OrgInfoDao.Exist(ctx, req.OrgId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_report_api.RemoveDayReportResponse{
			Code:   org_report_api.RemoveDayReportResponse_CODE_NO_ORG,
			ErrMsg: "组织不存在",
		}, nil
	}
	exist, err = org_dao.MemberDao.Exist(ctx, req.OrgId, sessionItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_report_api.RemoveDayReportResponse{
			Code:   org_report_api.RemoveDayReportResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	reportItem, err := org_dao.DayReportDao.Get(ctx, req.OrgId, sessionItem.UserId, req.ReportId)
	if err != nil { //记录不存在
		return &org_report_api.RemoveDayReportResponse{
			Code: org_report_api.RemoveDayReportResponse_CODE_OK,
		}, nil
	}
	nowTime := time.Now().UnixNano() / 1e6
	userPerm := apiImpl.calcDayReportPerm(sessionItem.UserId, reportItem, nowTime)
	if !userPerm.CanRemove {
		return &org_report_api.RemoveDayReportResponse{
			Code:   org_report_api.RemoveDayReportResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = org_dao.DayReportDao.Remove(sessCtx, req.OrgId, sessionItem.UserId, req.ReportId)
		if err != nil {
			return nil, err
		}
		return &org_report_api.RemoveDayReportResponse{
			Code: org_report_api.RemoveDayReportResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*org_report_api.RemoveDayReportResponse), nil
}
